/**
 * 
 */
package com.xpec.c4.service.group.transportlayer;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xpec.c4.codec.CodecUtility;
import com.xpec.c4.codec.manual.BytesManualDecode;
import com.xpec.c4.codec.manual.BytesManualEncode;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.net.codec.ManualCodec;
import com.xpec.c4.service.message.NetMessage;

/**
 * 组信息<br>
 * 
 * 當分別指定member fields數據時, <br>
 * 要先設定MessageType, 因為message type 會影響content的編碼!<br>
 * 
 * @author lipeilin
 * @2011-3-10 下午02:56:19
 * 
 */
public class GroupMessage implements ManualCodec {

	private static final Log log = LogFactory.getLog(GroupMessage.class);
	
	private static final byte[] defaultContentBytes = CodecUtility.encodeByte(null,-1);
	
	/**
	 * 廣播對象 (參照 BroadcastTargetTypes)
	 */
	private int broadCastTarget = BroadcastTargetTypes.BROADCAST_TO_LOBBY;
	
	/**
	 * 廣播目標module名稱 (參照 ModuleName，不含底線的)
	 */
	private String broadCastTargetModuleName;

	/**
	 * 目的服务器
	 */
	private String destModuleID;

	/**
	 * 源服务器
	 */
	private String srcService;

	/**
	 * 消息号
	 */
	private int messageType;
	
	/**
	 * 同步號碼
	 */
	private int syncId;

	/**
	 * 消息内容编码后的内容<br>
	 * 默认是null
	 */
	private byte[] messageContentBytes = defaultContentBytes;

	/**
	 * sessionID
	 */
	private GUID sessionID;
	
	/**
	 * 不傳的sessionID
	 */
	private GUID notSessionID;

	/**
	 * 多个的sessionID
	 */
	private Collection<GUID> sessionIDs;
	
	/**
	 * 頻道ID
	 */
	private int channelID = 0;

	/**
	 * 发给client的？
	 */
	private boolean toClient = false;

	/**
	 * 廣播消息是否要傳給機器人
	 */
	private boolean broadcastToRobot = false;

	/**
	 * 
	 */
	public GroupMessage() {
	}

	/**
	 * 
	 */
	public GroupMessage(NetMessage message) 
	{
		this.messageContentBytes = message.getMessageContentBytes();
		this.messageType = message.getMessageType();
		this.destModuleID = message.getModuleID();
		this.sessionID = message.getSessionID();
		this.toClient = true;
	}

	public void setMessageContent(Object content) 
	{
		this.messageContentBytes = CodecUtility.encodeByte(content,messageType);
	}
	
	

	@Override
	public String toString() {
		return "destModuleID:" + destModuleID + " \tsrcService:" + srcService
				+ " \tmessageType:" + messageType + " \tcontent:"
				+ messageContentBytes + " \tsessionID:" + sessionID;
	}

	public int getMessageType() {
		return messageType;
	}

	public void setMessageType(int messageType) {
		this.messageType = messageType;
	}

	public int getSyncId() {
		return syncId;
	}

	public void setSyncId(int syncId) {
		this.syncId = syncId;
	}
	
	public String getSrcService() {
		return srcService;
	}

	public void setSrcService(String srcService) {
		this.srcService = srcService;
	}

	public GUID getSessionID() {
		return sessionID;
	}

	public void setSessionID(GUID sessionID) {
		this.sessionID = sessionID;
	}

	public String getDestModuleID() {
		return destModuleID;
	}

	public void setDestModuleID(String destModuleID) {
		this.destModuleID = destModuleID;
	}

	public Collection<GUID> getSessionIDs() {
		return sessionIDs;
	}

	public void setSessionIDs(Collection<GUID> sessionIDs) {
		this.sessionIDs = sessionIDs;
	}

	public boolean isToClient() {
		return toClient;
	}

	public void setToClient(boolean toClient) {
		this.toClient = toClient;
	}

	public byte[] getMessageContentBytes() {
		return messageContentBytes;
	}

	public void setMessageContentBytes(byte[] messageContentBytes) {
		this.messageContentBytes = messageContentBytes;
	}
	
	public int getChannelID() {
		return channelID;
	}

	public void setChannelID(int channelID) {
		this.channelID = channelID;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.xpec.c4.service.codec.manual.ManualCodec#decode(byte[])
	 */
	@Override
	public void decode(byte[] bytes) 
	{
		// 需要传送的内容
		BytesManualDecode decode = new BytesManualDecode(bytes);
		srcService = decode.getString();
		destModuleID = decode.getString();
		toClient = decode.getBoolean();
		broadCast = decode.getBoolean();
		messageType = decode.getInt();
		syncId = decode.getInt();
		sessionIDs = decode.getCollectionUUID();
		messageContentBytes = decode.getArrayByte();
		channelID = decode.getInt();
		notSessionID = decode.getUUID();
		broadCastTarget = decode.getInt();
		broadCastTargetModuleName = decode.getString();
		broadcastToRobot = decode.getBoolean();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.xpec.c4.service.codec.manual.ManualCodec#encode()
	 */
	@Override
	public byte[] encode() {
		byte[] content = null;

		byte[] bytes = this.messageContentBytes;
			
		if (sessionID != null) 
		{
			if (sessionIDs == null) 
				sessionIDs = new ArrayList<GUID>();

			sessionIDs.add(sessionID);
		}

		// 编码
		int sessionLength = sessionIDs == null ? 0 : sessionIDs.size();
		int bytesLength = bytes == null ? 0 : bytes.length;
		int length = 40 + 40 + 1 + 4 + 4 + 4 + sessionLength * 40 + 4 + bytesLength + 4 + 40 + 40;
		BytesManualEncode encode = new BytesManualEncode(length);
		encode.putString(srcService);
		encode.putString(destModuleID);
		encode.putBoolean(toClient);
		encode.putBoolean(broadCast);		
		encode.putInt(messageType);
		encode.putInt(syncId);
		encode.putCollectionUUID(sessionIDs);
		encode.putArrayByte(bytes);
		encode.putInt(channelID);
		encode.putUUID(notSessionID);
		encode.putInt(broadCastTarget);
		encode.putString(broadCastTargetModuleName);
		encode.putBoolean(broadcastToRobot);

		try 
		{
			content = encode.asBytes();
		} 
		catch (Exception e) {
			log.error("encode error!", e);
			throw new RuntimeException(e);
		}
		return content;
	}

	private boolean broadCast = false;

	public boolean isBroadCast() {
		return broadCast;
	}

	public void setBroadCast(boolean broadCast) {
		this.broadCast = broadCast;
	}

	public GUID getNotSessionID() {
		return notSessionID;
	}

	public void setNotSessionID(GUID notSessionID) {
		this.notSessionID = notSessionID;
	}

	public int getBrocastTarget() {
		return broadCastTarget;
	}

	public void setBrocastTarget(int brocastTarget) {
		this.broadCastTarget = brocastTarget;
	}

	public String getBroadCastTargetModuleName() {
		return broadCastTargetModuleName;
	}

	public void setBroadCastTargetModuleName(String broadCastTargetModuleName) {
		this.broadCastTargetModuleName = broadCastTargetModuleName;
	}

	public boolean isBroadcastToRobot() {
		return broadcastToRobot;
	}

	public void setBroadcastToRobot(boolean broadcastToRobot) {
		this.broadcastToRobot = broadcastToRobot;
	}	
}
